<?php

/*
=====================================================
 FluxBB - Delux Board Converstations (DBC)
-----------------------------------------------------
 http://dbc-forum.com/
 http://fluxbb.org/
-----------------------------------------------------
 Copyright (c) 2010,2011 FluxBB - Delux Board Conversations (DBC)
-----------------------------------------------------
 Предсловие: Данный скрипт (DBC) не является работой с нуля, то 
 есть ядром скрипта всё также остаётся FuxBB,но теперь в оболочке
 DBC.
=====================================================
*/

// Make sure no one attempts to run this script "directly"
if (!defined('DBC'))
	exit;

// Global variables
/* regular expression to match nested BBCode LIST tags
'%
\[list                # match opening bracket and tag name of outermost LIST tag
(?:=([1a*]))?+        # optional attribute capture in group 1
\]                    # closing bracket of outermost opening LIST tag
(                     # capture contents of LIST tag in group 2
  (?:                 # non capture group for either contents or whole nested LIST
    [^\[]*+           # unroll the loop! consume everything up to next [ (normal *)
    (?:               # (See "Mastering Regular Expressions" chapter 6 for details)
      (?!             # negative lookahead ensures we are NOT on [LIST*] or [/LIST]
        \[list        # opening LIST tag
        (?:=[1a*])?+  # with optional attribute
        \]            # closing bracket of opening LIST tag
        |             # or...
        \[/list\]     # a closing LIST tag
      )               # end negative lookahead assertion (we are not on a LIST tag)
      \[              # match the [ which is NOT the start of LIST tag (special)
      [^\[]*+         # consume everything up to next [ (normal *)
    )*+               # finish up "unrolling the loop" technique (special (normal*))*
  |                   # or...
    (?R)              # recursively match a whole nested LIST element
  )*                  # as many times as necessary until deepest nested LIST tag grabbed
)                     # end capturing contents of LIST tag into group 2
\[/list\]             # match outermost closing LIST tag
%iex' */
$re_list = '%\[list(?:=([1a*]))?+\]((?:[^\[]*+(?:(?!\[list(?:=[1a*])?+\]|\[/list\])\[[^\[]*+)*+|(?R))*)\[/list\]%ie';

// Here you can add additional smilies if you like (please note that you must escape single quote and backslash)
/*
$smilies = array(
	':)' => 'smile.png',
	'=)' => 'smile.png',
	':|' => 'neutral.png',
	'=|' => 'neutral.png',
	':(' => 'sad.png',
	'=(' => 'sad.png',
	':D' => 'big_smile.png',
	'=D' => 'big_smile.png',
	':o' => 'yikes.png',
	':O' => 'yikes.png',
	';)' => 'wink.png',
	':/' => 'hmm.png',
	':P' => 'tongue.png',
	':p' => 'tongue.png',
	':lol:' => 'lol.png',
	':mad:' => 'mad.png',
	':rolleyes:' => 'roll.png',
	':cool:' => 'cool.png');
*/

if (!isset($smilies))
{
	if (file_exists(FORUM_CACHE_DIR.'cache_smilies.php'))
		include FORUM_CACHE_DIR.'cache_smilies.php';
	else
	{
		require_once DBC_ROOT.'engine/cache_smilies.php';
		generate_smiley_cache();
		require FORUM_CACHE_DIR.'cache_smilies.php';
	}
}

//
// Make sure all BBCodes are lower case and do a little cleanup
//
function preparse_bbcode($text, &$errors, $is_signature = false)
{
	global $DBC_config, $lang_common, $re_list;

	if ($is_signature)
	{
		global $lang_profile;

		if (preg_match('%\[/?(?:quote|code|list|title|h|hr|size|video|youtube|audio|after|spoiler)\b[^\]]*\]%i', $text))
			$errors[] = $lang_profile['Signature quote/code/list/h'];
	}

	// If the message contains a code tag we have to split it up (text within [code][/code] shouldn't be touched)
	if (strpos($text, '[code]') !== false && strpos($text, '[/code]') !== false)
	{
		list($inside, $outside) = split_text($text, '[code]', '[/code]', $errors);
		$text = implode("\1", $outside);
	}

	if (strpos($text, '[title]') !== false && strpos($text, '[/title]') !== false)
	{
		list($inside_title, $outside_title) = split_text($text, '[title]', '[/title]', $errors);
		$text = implode("\1", $outside_title);
	}

	// Tidy up lists
	$temp = preg_replace($re_list, 'preparse_list_tag(\'$2\', \'$1\', $errors)', $text);

	// If the regex failed
	if ($temp === null)
		$errors[] = $lang_common['BBCode list size error'];
	else
		$text = str_replace('*'."\0".']', '*]', $temp);

	if ($DBC_config['o_make_links'] == '1')
		$text = do_clickable($text);

	// If we split up the message before we have to concatenate it together again (code tags)
	if (isset($inside))
	{
		$outside = explode("\1", $text);
		$text = '';

		$num_tokens = count($outside);

		for ($i = 0; $i < $num_tokens; ++$i)
		{
			$text .= $outside[$i];
			if (isset($inside[$i]))
				$text .= '[code]'.$inside[$i].'[/code]';
		}
	}
	unset($inside);

	$temp_text = false;
	if (empty($errors))
		$temp_text = preparse_tags($text, $errors, $is_signature);

	if ($temp_text !== false)
		$text = $temp_text;

	// Remove empty tags
	while (($new_text = strip_empty_bbcode($text, $errors)) !== false)
	{
		if ($new_text != $text)
			$text = $new_text;
		else
			break;
	}

	return DBC_trim($text);
}


//
// Strip empty bbcode tags from some text
//
function strip_empty_bbcode($text, &$errors)
{
	// If the message contains a code tag we have to split it up (empty tags within [code][/code] are fine)
	if (strpos($text, '[code]') !== false && strpos($text, '[/code]') !== false)
	{
		list($inside, $outside) = split_text($text, '[code]', '[/code]', $errors);
		$text = implode("\1", $outside);
	}

	// Remove empty tags
	while (($new_text = preg_replace('/\[(b|u|s|ins|del|em|title|i|h|colou?r|quote|img|imgl|imgr|url|email|list|hr|size|video|youtube|audio|after|spoiler|right|center|justify|mono)(?:\=[^\]]*)?\]\s*\[\/\1\]/', '', $text)) !== false)
	{
		if ($new_text != $text)
			$text = $new_text;
		else
			break;
	}

	// If we split up the message before we have to concatenate it together again (code tags)
	if (isset($inside))
	{
		$outside = explode("\1", $text);
		$text = '';

		$num_tokens = count($outside);
		for ($i = 0; $i < $num_tokens; ++$i)
		{
			$text .= $outside[$i];
			if (isset($inside[$i]))
				$text .= '[code]'.$inside[$i].'[/code]';
		}
	}

	// Remove empty code tags
	while (($new_text = preg_replace('/\[(code)\]\s*\[\/\1\]/', '', $text)) !== false)
	{
		if ($new_text != $text)
			$text = $new_text;
		else
			break;
	}

	return $text;
}


//
// Check the structure of bbcode tags and fix simple mistakes where possible
//
function preparse_tags($text, &$errors, $is_signature = false)
{
	global $lang_common, $DBC_config;

	// Start off by making some arrays of bbcode tags and what we need to do with each one

	// List of all the tags
	$tags = array('quote', 'code', 'b', 'i', 'u', 's', 'ins', 'del', 'title', 'em', 'color', 'colour', 'url', 'email', 'img', 'imgl', 'imgr', 'list', '*', 'h','size', 'video', 'youtube', 'audio', 'spoiler', 'right', 'center', 'justify', 'mono');
	// List of tags that we need to check are open (You could not put b,i,u in here then illegal nesting like [b][i][/b][/i] would be allowed)
	$tags_opened = $tags;
	// and tags we need to check are closed (the same as above, added it just in case)
	$tags_closed = $tags;
	// Tags we can nest and the depth they can be nested to (only quotes)
	$tags_nested = array('quote' => $DBC_config['o_quote_depth'], 'list' => 5, '*' => 5, 'spoiler' => 5);
	// Tags to ignore the contents of completely (just code)
	$tags_ignore = array('code');
	// Block tags, block tags can only go within another block tag, they cannot be in a normal tag
	$tags_block = array('quote', 'title', 'code', 'list', 'h', '*', 'spoiler');
	// Inline tags, we do not allow new lines in these
	$tags_inline = array('b', 'i', 'u', 's', 'ins', 'del', 'title', 'em', 'color', 'colour', 'h');
	// Tags we trim interior space
	$tags_trim = array('img', 'imgl', 'imgr');
	// Tags we remove quotes from the argument
	$tags_quotes = array('url', 'email', 'img', 'imgl', 'imgr', 'audio', 'video', 'youtube');
	// Tags we limit bbcode in
	$tags_limit_bbcode = array(
		'*' 	=> array('b', 'i', 'u', 's', 'ins', 'del', 'title', 'em', 'color', 'colour', 'url', 'email', 'list', 'img', 'imgl', 'imgr', 'code'),
		'list' 	=> array('*'),
		'url' 	=> array('b', 'i', 'u', 's', 'ins', 'del', 'em', 'color', 'colour', 'img', 'imgr', 'imgl'),
		'email' => array('b', 'i', 'u', 's', 'ins', 'del', 'title', 'em', 'color', 'colour', 'img', 'imgr', 'imgl'),
		'img' 	=> array(),
		'imgr' 	=> array(),
		'imgl' 	=> array(),
		'h'		=> array('b', 'i', 'u', 's', 'ins', 'del', 'title', 'em', 'color', 'colour', 'url', 'email'),
	);
	// Tags we can automatically fix bad nesting
	$tags_fix = array('quote', 'b', 'i', 'u', 's', 'ins', 'del', 'title', 'em', 'color', 'colour', 'url', 'email', 'h');

	$split_text = preg_split("/(\[[\*a-zA-Z0-9-\/]*?(?:=.*?)?\])/", $text, -1, PREG_SPLIT_DELIM_CAPTURE|PREG_SPLIT_NO_EMPTY);

	$open_tags = array('post');
	$open_args = array('');
	$opened_tag = 0;
	$new_text = '';
	$current_ignore = '';
	$current_nest = '';
	$current_depth = array();
	$limit_bbcode = $tags;

	foreach ($split_text as $current)
	{
		if ($current == '')
			continue;

		// Are we dealing with a tag?
		if (substr($current, 0, 1) != '[' || substr($current, -1, 1) != ']')
		{
			// It's not a bbcode tag so we put it on the end and continue

			// If we are nested too deeply don't add to the end
			if ($current_nest)
				continue;

			$current = str_replace("\r\n", "\n", $current);
			$current = str_replace("\r", "\n", $current);
			if (in_array($open_tags[$opened_tag], $tags_inline) && strpos($current, "\n") !== false)
			{
				// Deal with new lines
				$split_current = preg_split("/(\n\n+)/", $current, -1, PREG_SPLIT_DELIM_CAPTURE|PREG_SPLIT_NO_EMPTY);
				$current = '';

				if (!DBC_trim($split_current[0], "\n")) // The first part is a linebreak so we need to handle any open tags first
					array_unshift($split_current, '');

				for ($i = 1; $i < count($split_current); $i += 2)
				{
					$temp_opened = array();
					$temp_opened_arg = array();
					$temp = $split_current[$i - 1];
					while (!empty($open_tags))
					{
						$temp_tag = array_pop($open_tags);
						$temp_arg = array_pop($open_args);

						if (in_array($temp_tag , $tags_inline))
						{
							array_push($temp_opened, $temp_tag);
							array_push($temp_opened_arg, $temp_arg);
							$temp .= '[/'.$temp_tag.']';
						}
						else
						{
							array_push($open_tags, $temp_tag);
							array_push($open_args, $temp_arg);
							break;
						}
					}
					$current .= $temp.$split_current[$i];
					$temp = '';
					while (!empty($temp_opened))
					{
						$temp_tag = array_pop($temp_opened);
						$temp_arg = array_pop($temp_opened_arg);
						if (empty($temp_arg))
							$temp .= '['.$temp_tag.']';
						else
							$temp .= '['.$temp_tag.'='.$temp_arg.']';
						array_push($open_tags, $temp_tag);
						array_push($open_args, $temp_arg);
					}
					$current .= $temp;
				}

				if (array_key_exists($i - 1, $split_current))
					$current .= $split_current[$i - 1];
			}

			if (in_array($open_tags[$opened_tag], $tags_trim))
				$new_text .= DBC_trim($current);
			else
				$new_text .= $current;

			continue;
		}

		// Get the name of the tag
		$current_arg = '';
		if (strpos($current, '/') === 1)
		{
			$current_tag = substr($current, 2, -1);
		}
		else if (strpos($current, '=') === false)
		{
			$current_tag = substr($current, 1, -1);
		}
		else
		{
			$current_tag = substr($current, 1, strpos($current, '=')-1);
			$current_arg = substr($current, strpos($current, '=')+1, -1);
		}
		$current_tag = strtolower($current_tag);

		// Is the tag defined?
		if (!in_array($current_tag, $tags))
		{
			// It's not a bbcode tag so we put it on the end and continue
			if (!$current_nest)
				$new_text .= $current;

			continue;
		}

		// We definitely have a bbcode tag

		// Make the tag string lower case
		if ($equalpos = strpos($current,'='))
		{
			// We have an argument for the tag which we don't want to make lowercase
			if (strlen(substr($current, $equalpos)) == 2)
			{
				// Empty tag argument
				$errors[] = sprintf($lang_common['BBCode error empty attribute'], $current_tag);
				return false;
			}
			$current = strtolower(substr($current, 0, $equalpos)).substr($current, $equalpos);
		}
		else
			$current = strtolower($current);

		// This is if we are currently in a tag which escapes other bbcode such as code
		if ($current_ignore)
		{
			if ('[/'.$current_ignore.']' == $current)
			{
				// We've finished the ignored section
				$current = '[/'.$current_tag.']';
				$current_ignore = '';
			}

			$new_text .= $current;

			continue;
		}

		if ($current_nest)
		{
			// We are currently too deeply nested so lets see if we are closing the tag or not
			if ($current_tag != $current_nest)
				continue;

			if (substr($current, 1, 1) == '/')
				$current_depth[$current_nest]--;
			else
				$current_depth[$current_nest]++;

			if ($current_depth[$current_nest] <= $tags_nested[$current_nest])
				$current_nest = '';

			continue;
		}

		// Check the current tag is allowed here
		if (!in_array($current_tag, $limit_bbcode) && $current_tag != $open_tags[$opened_tag])
		{
			$errors[] = sprintf($lang_common['BBCode error invalid nesting'], $current_tag, $open_tags[$opened_tag]);
			return false;
		}

		if (substr($current, 1, 1) == '/')
		{
			// This is if we are closing a tag

			if ($opened_tag == 0 || !in_array($current_tag, $open_tags))
			{
				// We tried to close a tag which is not open
				if (in_array($current_tag, $tags_opened))
				{
					$errors[] = sprintf($lang_common['BBCode error no opening tag'], $current_tag);
					return false;
				}
			}
			else
			{
				// Check nesting
				while (true)
				{
					// Nesting is ok
					if ($open_tags[$opened_tag] == $current_tag)
					{
						array_pop($open_tags);
						array_pop($open_args);
						$opened_tag--;
						break;
					}

					// Nesting isn't ok, try to fix it
					if (in_array($open_tags[$opened_tag], $tags_closed) && in_array($current_tag, $tags_closed))
					{
						if (in_array($current_tag, $open_tags))
						{
							$temp_opened = array();
							$temp_opened_arg = array();
							$temp = '';
							while (!empty($open_tags))
							{
								$temp_tag = array_pop($open_tags);
								$temp_arg = array_pop($open_args);

								if (!in_array($temp_tag, $tags_fix))
								{
									// We couldn't fix nesting
									$errors[] = sprintf($lang_common['BBCode error no closing tag'], array_pop($temp_opened));
									return false;
								}
								array_push($temp_opened, $temp_tag);
								array_push($temp_opened_arg, $temp_arg);

								if ($temp_tag == $current_tag)
									break;
								else
									$temp .= '[/'.$temp_tag.']';
							}
							$current = $temp.$current;
							$temp = '';
							array_pop($temp_opened);
							array_pop($temp_opened_arg);

							while (!empty($temp_opened))
							{
								$temp_tag = array_pop($temp_opened);
								$temp_arg = array_pop($temp_opened_arg);
								if (empty($temp_arg))
									$temp .= '['.$temp_tag.']';
								else
									$temp .= '['.$temp_tag.'='.$temp_arg.']';
								array_push($open_tags, $temp_tag);
								array_push($open_args, $temp_arg);
							}
							$current .= $temp;
							$opened_tag--;
							break;
						}
						else
						{
							// We couldn't fix nesting
							$errors[] = sprintf($lang_common['BBCode error no opening tag'], $current_tag);
							return false;
						}
					}
					else if (in_array($open_tags[$opened_tag], $tags_closed))
						break;
					else
					{
						array_pop($open_tags);
						array_pop($open_args);
						$opened_tag--;
					}
				}
			}

			if (in_array($current_tag, array_keys($tags_nested)))
			{
				if (isset($current_depth[$current_tag]))
					$current_depth[$current_tag]--;
			}

			if (in_array($open_tags[$opened_tag], array_keys($tags_limit_bbcode)))
				$limit_bbcode = $tags_limit_bbcode[$open_tags[$opened_tag]];
			else
				$limit_bbcode = $tags;

			$new_text .= $current;

			continue;
		}
		else
		{
			// We are opening a tag
			if (in_array($current_tag, array_keys($tags_limit_bbcode)))
				$limit_bbcode = $tags_limit_bbcode[$current_tag];
			else
				$limit_bbcode = $tags;

			if (in_array($current_tag, $tags_block) && !in_array($open_tags[$opened_tag], $tags_block) && $opened_tag != 0)
			{
				// We tried to open a block tag within a non-block tag
				$errors[] = sprintf($lang_common['BBCode error invalid nesting'], $current_tag, $open_tags[$opened_tag]);
				return false;
			}

			if (in_array($current_tag, $tags_ignore))
			{
				// It's an ignore tag so we don't need to worry about what's inside it
				$current_ignore = $current_tag;
				$new_text .= $current;
				continue;
			}

			// Deal with nested tags
			if (in_array($current_tag, $open_tags) && !in_array($current_tag, array_keys($tags_nested)))
			{
				// We nested a tag we shouldn't
				$errors[] = sprintf($lang_common['BBCode error invalid self-nesting'], $current_tag);
				return false;
			}
			else if (in_array($current_tag, array_keys($tags_nested)))
			{
				// We are allowed to nest this tag

				if (isset($current_depth[$current_tag]))
					$current_depth[$current_tag]++;
				else
					$current_depth[$current_tag] = 1;

				// See if we are nested too deep
				if ($current_depth[$current_tag] > $tags_nested[$current_tag])
				{
					$current_nest = $current_tag;
					continue;
				}
			}

			// Remove quotes from arguments for certain tags
			if (strpos($current, '=') !== false && in_array($current_tag, $tags_quotes))
			{
				$current = preg_replace('#\['.$current_tag.'=("|\'|)(.*?)\\1\]\s*#i', '['.$current_tag.'=$2]', $current);
			}

			if (in_array($current_tag, array_keys($tags_limit_bbcode)))
				$limit_bbcode = $tags_limit_bbcode[$current_tag];

			$open_tags[] = $current_tag;
			$open_args[] = $current_arg;
			$opened_tag++;
			$new_text .= $current;
			continue;
		}
	}

	// Check we closed all the tags we needed to
	foreach ($tags_closed as $check)
	{
		if (in_array($check, $open_tags))
		{
			// We left an important tag open
			$errors[] = sprintf($lang_common['BBCode error no closing tag'], $check);
			return false;
		}
	}

	if ($current_ignore)
	{
		// We left an ignore tag open
		$errors[] = sprintf($lang_common['BBCode error no closing tag'], $current_ignore);
		return false;
	}

	return $new_text;
}


//
// Preparse the contents of [list] bbcode
//
function preparse_list_tag($content, $type = '*', &$errors)
{
	global $lang_common, $re_list;

	if (strlen($type) != 1)
		$type = '*';

	if (strpos($content,'[list') !== false)
	{
		$content = preg_replace($re_list, 'preparse_list_tag(\'$2\', \'$1\', $errors)', $content);
	}

	$items = explode('[*]', str_replace('\"', '"', $content));

	$content = '';
	foreach ($items as $item)
	{
		if (DBC_trim($item) != '')
			$content .= '[*'."\0".']'.str_replace('[/*]', '', DBC_trim($item)).'[/*'."\0".']'."\n";
	}

	return '[list='.$type.']'."\n".$content.'[/list]';
}


//
// Split text into chunks ($inside contains all text inside $start and $end, and $outside contains all text outside)
//
function split_text($text, $start, $end, &$errors, $retab = true)
{
	global $DBC_config, $lang_common;

	$tokens = explode($start, $text);

	$outside[] = $tokens[0];

	$num_tokens = count($tokens);
	for ($i = 1; $i < $num_tokens; ++$i)
	{
		$temp = explode($end, $tokens[$i]);

		if (count($temp) != 2)
		{
			$errors[] = $lang_common['BBCode code problem'];
			return array(null, array($text));
		}
		$inside[] = $temp[0];
		$outside[] = $temp[1];
	}

	if ($DBC_config['o_indent_num_spaces'] != 8 && $retab)
	{
		$spaces = str_repeat(' ', $DBC_config['o_indent_num_spaces']);
		$inside = str_replace("\t", $spaces, $inside);
	}

	return array($inside, $outside);
}


//
// Truncate URL if longer than 55 characters (add http:// or ftp:// if missing)
//

function handle_url_tag($url, $link = '', $bbcode = false)
{
	global $DBC_config, $lang_common, $DBC_user;
	
	$url = DBC_trim($url);
	$full_url = str_replace(array(' ', '\'', '`', '"'), array('%20', '', '', ''), $url);
	if (strpos($url, 'www.') === 0) // If it starts with www, we add http://
		$full_url = 'http://'.$full_url;
	else if (strpos($url, 'ftp.') === 0) // Else if it starts with ftp, we add ftp://
		$full_url = 'ftp://'.$full_url;
	else if (strpos($url, '/') === 0) // Allow for relative URLs that start with a slash
		$full_url = get_base_url(true).$full_url;
	else if (!preg_match('#^([a-z0-9]{3,6})://#', $url)) // Else if it doesn't start with abcdef://, we add http://
		$full_url = 'http://'.$full_url;

	// Ok, not very pretty :-)
	if ($bbcode)
	{
		if ($full_url == $link)
			return '[url]'.$link.'[/url]';
		else
			return '[url='.$full_url.']'.$link.'[/url]';
	}
	else if ($DBC_config['o_board_redirect'] == '' || (!$DBC_user['is_guest'] && $DBC_config['o_board_redirectg'] == '1') || preg_match('/'.$DBC_config['o_board_redirect'].'/i',$full_url))
	{
		if ($link == '' || $link == $url)
		{
			$url = DBC_htmlspecialchars_decode($url);
			$link = utf8_strlen($url) > 55 ? utf8_substr($url, 0 , 39).' … '.utf8_substr($url, -10) : $url;
			$link = DBC_htmlspecialchars($link);
		}
		else
			$link = stripslashes($link);

		return '<a href="'.$full_url.'">'.$link.'</a>';
	}
	else
	{
		if ($link == '' || $link == $url)
		{
			$url = DBC_htmlspecialchars_decode($url);
			$link = utf8_strlen($url) > 55 ? utf8_substr($url, 0 , 39).' … '.utf8_substr($url, -10) : $url;
			$link = DBC_htmlspecialchars($link);
		}
		else
			$link = stripslashes($link);

		return '<a href="re.php?u='.urlencode($full_url).'">'.$link.'</a>';
	}
}


//
// Turns an URL from the [img] tag into an <img> tag or a <a href...> tag
//
function handle_img_tag($url, $is_signature = false, $alt = null, $float = '')
{
	global $lang_common, $DBC_user;

	if ($alt == null)
		$alt = basename($url);

	$img_tag = '<p><a href="'.$url.'" rel="iLoad" title="'.$alt.'" class="hs_bg">&#8594; &lt;'.$lang_common['Image link'].' - '.$alt.'&gt;</a></p><a href="'.$url.'" title="" rel="iLoad" class="hs_bg"><img src="'.$url.'" '.(($float != '') ? 'style="float: '.$float.'; clear: '.$float.'" ' : '').'alt=""  class="iload_image" style="display: inline; "/></a>';

	if ($is_signature && $DBC_user['show_img_sig'] != '0')
		$img_tag = '<img class="sigimage" src="'.$url.'" alt="" />';
	else if (!$is_signature && $DBC_user['show_img'] != '0')
		$img_tag = '<a href="'.$url.'" rel="iLoad" title="" class="hs_bg"><img src="'.$url.'" '.(($float != '') ? 'style="float: '.$float.'; clear: '.$float.'" ' : '').' alt="" style="display: inline; " class="iload_image"/></a>';

	return $img_tag;
}


//
// Parse the contents of [list] bbcode
//
function handle_list_tag($content, $type = '*')
{
	global $re_list;

	if (strlen($type) != 1)
		$type = '*';

	if (strpos($content,'[list') !== false)
	{
		$content = preg_replace($re_list, 'handle_list_tag(\'$2\', \'$1\')', $content);
	}

	$content = preg_replace('#\s*\[\*\](.*?)\[/\*\]\s*#s', '<li><p><span>$1</span></p></li>', DBC_trim($content));

	if ($type == '*')
		$content = '<ul class="listing">'.$content.'</ul>';
	else
		if ($type == 'a')
			$content = '<ol class="alpha">'.$content.'</ol>';
		else
			$content = '<ol class="decimal">'.$content.'</ol>';

	return '</p>'.$content.'<p>';
}

//
function handle_time_tag($after_time)
{
	global $lang_common;

	if ($after_time == 0)
    return '';
    
	$content = array();
	$merged_sec = $after_time % 60;
	$merged_min = ($after_time/60) % 60;
	$merged_hours = ($after_time/3600) % 24;
	$merged_days = intval($after_time/86400);
	if ($merged_days > 0)
		$content[] = $merged_days.$lang_common['After time d'];
	if ($merged_hours > 0)
		$content[] = $merged_hours.$lang_common['After time H'];
	if ($merged_min > 0)
		$content[] = (($merged_min < 10) ? '0'.$merged_min : $merged_min).$lang_common['After time i'];
	if ($merged_sec > 0)
		$content[] = (($merged_sec < 10) ? '0'.$merged_sec : $merged_sec).$lang_common['After time s'];

	return DBC_linebreaks(DBC_trim('<span style="color: #808080"><em>'.$lang_common['After time'].' '.implode(' ', $content).':</em></span>'."\n"));

}

//
// Convert BBCodes to their HTML equivalent
//
function do_bbcode($text, $is_signature = false)
{
	global $lang_common, $DBC_user, $DBC_config, $re_list;
	require DBC_ROOT.'language/'.$DBC_user['language'].'/topic.php';

	if (strpos($text, '[quote') !== false)
	{
		$text = preg_replace('#\[quote\]\s*#', '</p><div class="quotebox"><blockquote><div><p>', $text);
		$text = preg_replace('#\[quote=(&quot;|"|\'|)(.*?)\\1\]#se', '"</p><div class=\"quote_box\"><div class=\"title_quote\">".str_replace(array(\'[\', \'\\"\'), array(\'&#91;\', \'"\'), \'$2\')." ".$lang_common[\'wrote\']."</div><blockquote><div class=\"quote quote_p\"><p>"', $text);
		$text = preg_replace('#\s*\[\/quote\]#S', '</p></div></blockquote></div><p>', $text);
	}

	if (strpos($text, '[spoiler]') !== false)
	{
		$text = str_replace('[spoiler]', "<div> <div class=\"title_spoiler spoiler_t\"><b>".$lang_common['Hidden text']."</b>: <input type=\"button\" value=\"".$lang_common['Show']."\" style=\"width:60px;font-size:10px;margin:0px;padding:0px;\" onClick=\"if (this.parentNode.parentNode.getElementsByTagName('div')[1].getElementsByTagName('div')[0].style.display != '') { this.parentNode.parentNode.getElementsByTagName('div')[1].getElementsByTagName('div')[0].style.display = ''; this.innerText = ''; this.value = '".$lang_common['Hide']."'; } else { this.parentNode.parentNode.getElementsByTagName('div')[1].getElementsByTagName('div')[0].style.display = 'none'; this.innerText = ''; this.value = '".$lang_common['Show']."'; }\"> </div> <div><div style=\"display: none;\" class=\"text_spoiler spoiler_c\"> ", $text);
		$text = str_replace('[/spoiler]', '</div> </div> </div>', $text);
	}

	if (strpos($text, '[title') !== false)
	{
		$text = preg_replace('#\[title\]\s*#', '</p><div><p>', $text);
		$text = preg_replace('#\[title=(&quot;|"|\'|)(.*?)\\1\]#se', '"</p><div class=\"title_tag\">".str_replace(array(\'[\', \'\\"\'), array(\'&#91;\', \'"\'), \'$2\')." </div><div class=\"title_tag_text\"><p>"', $text);
		$text = preg_replace('#\s*\[\/title\]#S', '</p></div><p>', $text);
	}




  // bbcode VIDEO
 	if (strpos($text, '[video') !== false)
	{
		$text = preg_replace('#\[video\](http.*mp4)\[/video\]#U',
			'</p><div class="bbvideo">'.
			'<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,0,0" id="Player-eaa5f19509b24466ae4503b4544352b1" height="325" width="425">'.
			'<param name="movie" value="engine/classes/swf/media_player.swf?MediaLink=$1&amp;defaultMedia=1&amp;logo=http://localhost/9.2/templates/Default/dleimages/flv_watermark.png&amp;showPlayButton=true&amp;playOnStart=false&amp;backgroundBarColor=0x01669a&amp;btnsColor=0xFFFFFF&amp;outlineColor=0x1A75A4&amp;outputBkgColor=0x025B87&amp;outputTxtColor=0xffffff&amp;loadingBarColor=0xffffff&amp;loadingBackgroundColor=0x8ED9FF&amp;progressBarColor=0x8ED9FF&amp;volumeBackgroundColor=0x01669a&amp;volumeStatusBarColor=0x8ED9FF">'.
			'<param name="allowFullScreen" value="true">'.
			'<param name="quality" value="high">'.
			'<param name="bgcolor" value="#000000">'.
			'<param name="wmode" value="opaque">'.
			'<embed src="engine/classes/swf/media_player.swf?MediaLink=$1&amp;defaultMedia=1&amp;logo=http://localhost/9.2/templates/Default/dleimages/flv_watermark.png&amp;showPlayButton=true&amp;playOnStart=false&amp;backgroundBarColor=0x01669a&amp;btnsColor=0xFFFFFF&amp;outlineColor=0x1A75A4&amp;outputBkgColor=0x025B87&amp;outputTxtColor=0xffffff&amp;loadingBarColor=0xffffff&amp;loadingBackgroundColor=0x8ED9FF&amp;progressBarColor=0x8ED9FF&amp;volumeBackgroundColor=0xffffff&amp;volumeStatusBarColor=0x8ED9FF" quality="high" wmode="transparent" allowfullscreen="false" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" height="325" width="425" align="middle" style="-moz-border-radius: 5px;-webkit-border-radius: 5px;border-radius: 5px;">'.
			'</object> </div><p>', $text);
	}
	
  // bbcode YOUTUBE
 	if (strpos($text, '[youtube') !== false)
	{
		$text = preg_replace("/\[youtube\](.*)youtube.com\/watch\?v=(.*)\[\/youtube\]/Usi",
			"<object width=\"425\" height=\"344\"><param name=\"movie\" value=\"http://www.youtube.com/v/\\2&hl=de&fs=1\"></param>".
			"<param name=\"allowFullScreen\" value=\"true\"></param>".
			"<embed src=\"http://www.youtube.com/v/\\2&hl=de&fs=1\" type=\"application/x-shockwave-flash\" allowfullscreen=\"true\" width=\"425\" height=\"344\"></embed></object>",
			$text);
	}



  // bbcode AUDIO
	if (strpos($text, '[audio') !== false)
	{
		$text = preg_replace('#\[audio\](http.*mp3)\[/audio\]#U',
			'</p><div class="bbvideo">'.
			'<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,0,0" id="Player-6c552cf9971ca2c6a664ee6fc3ee637f" height="30" width="425">'.
			'<param name="movie" value="engine/classes/swf/media_player.swf?MediaLink=$1&amp;defaultMedia=1&amp;showPlayButton=false&amp;playOnStart=false&amp;backgroundBarColor=0x01669a&amp;btnsColor=0xFFFFFF&amp;outlineColor=0x1A75A4&amp;outputBkgColor=0x025B87&amp;outputTxtColor=0xffffff&amp;loadingBarColor=0xffffff&amp;loadingBackgroundColor=0x8ED9FF&amp;progressBarColor=0x8ED9FF&amp;volumeBackgroundColor=0x01669a&amp;volumeStatusBarColor=0x8ED9FF">'.
			'<param name="allowFullScreen" value="false">'.
			'<param name="quality" value="high">'.
			'<param name="wmode" value="transparent">'.
			'<embed src="engine/classes/swf/media_player.swf?MediaLink=$1&amp;defaultMedia=1&amp;showPlayButton=false&amp;playOnStart=false&amp;backgroundBarColor=0x01669a&amp;btnsColor=0xFFFFFF&amp;outlineColor=0x1A75A4&amp;outputBkgColor=0x025B87&amp;outputTxtColor=0xffffff&amp;loadingBarColor=0xffffff&amp;loadingBackgroundColor=0x8ED9FF&amp;progressBarColor=0x8ED9FF&amp;volumeBackgroundColor=0xffffff&amp;volumeStatusBarColor=0x8ED9FF" quality="high" wmode="transparent" allowfullscreen="false" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" height="30" width="425" align="middle" style="-moz-border-radius: 5px;-webkit-border-radius: 5px;border-radius: 5px;">'.
			'</object> </div><p>', $text);
	}

	if (!$is_signature)
	{
		$pattern[] = $re_list;
		$replace[] = 'handle_list_tag(\'$2\', \'$1\')';
	}

    if (strpos($text, 'hide') !== false)
    {
        if ($DBC_user['is_guest'])
        {
                $text = preg_replace("#\[hide\](.+?)\[/hide\]#is", '['.$lang_topic['Hidden text guest'].']', $text);
        }
        else if(($DBC_user['g_id'] == DBC_MOD) || ($DBC_user['g_id'] == DBC_ADMIN) || ($DBC_user['num_post_in_topic'] > 0))
        {
            $text = str_replace('[hide]', '<blockquote>'.$lang_topic['Hidden text'].':<br/><i>', $text);
            $text = preg_replace('#\[\/hide\]\s*#', '</i></blockquote>', $text);

        }
        else 
        {
                $text = preg_replace("#\[hide\](.+?)\[/hide\]#is", '['.$lang_topic['Hidden text num_post'].']', $text);
        }
    }

	$pattern[] = '#\[b\](.*?)\[/b\]#ms';
	$pattern[] = '#\[i\](.*?)\[/i\]#ms';
	$pattern[] = '#\[h\](.*?)\[/h\]#s';
	$pattern[] = '#\[u\](.*?)\[/u\]#ms';
	$pattern[] = '#\[s\](.*?)\[/s\]#ms';
	$pattern[] = '#\[del\](.*?)\[/del\]#ms';
	$pattern[] = '#\[title\](.*?)\[/title\]#ms';
	$pattern[] = '#\[ins\](.*?)\[/ins\]#ms';
	$pattern[] = '#\[em\](.*?)\[/em\]#ms';
	$pattern[] = '#\[colou?r=([a-zA-Z]{3,20}|\#[0-9a-fA-F]{6}|\#[0-9a-fA-F]{3})](.*?)\[/colou?r\]#ms';
	$pattern[] = '#\[h\](.*?)\[/h\]#ms';
	$pattern[] = '#\[hr\]#';
	$pattern[] = '#\[size=([0-9]*)](.*?)\[/size\]#s';
	$pattern[] = '#\[after=([0-9]*)\]#e';
	$pattern[] = '#\[right\](.*?)\[/right\]#ms';
	$pattern[] = '#\[center\](.*?)\[/center\]#ms';
	$pattern[] = '#\[justify\](.*?)\[/justify\]#ms';
	$pattern[] = '#\[mono\](.*?)\[/mono\]#ms';

	$replace[] = '<strong>$1</strong>';
	$replace[] = '<em>$1</em>';
	$replace[] = '<span style="background-color: #FFFF00; color: #000000">$1</span>';
	$replace[] = '<span class="bbu">$1</span>';
	$replace[] = '<span class="bbs">$1</span>';
	$replace[] = '<del>$1</del>';
	$replace[] = '<title>$1</title>';
	$replace[] = '<ins>$1</ins>';
	$replace[] = '<em>$1</em>';
	$replace[] = '<span style="color: $1">$2</span>';
	$replace[] = '</p><h5>$1</h5><p>';
	$replace[] = '<hr />';
	$replace[] = '<span style="font-size: $1px">$2</span>';
	$replace[] = 'handle_time_tag(\'$1\')';
	$replace[] = '</p><p style="text-align: right">$1</p><p>';
	$replace[] = '</p><p style="text-align: center">$1</p><p>';
	$replace[] = '</p><p style="text-align: justify">$1</p><p>';
	$replace[] = '<code>$1</code>';

	if (($is_signature && $DBC_config['p_sig_img_tag'] == '1') || (!$is_signature && $DBC_config['p_message_img_tag'] == '1'))
	{
		$pattern[] = '#\[img\]((ht|f)tps?://)([^\s<"]*?)\[/img\]#e';
		$pattern[] = '#\[img=([^\[]*?)\]((ht|f)tps?://)([^\s<"]*?)\[/img\]#e';
		if ($is_signature)
		{
			$replace[] = 'handle_img_tag(\'$1$3\', true)';
			$replace[] = 'handle_img_tag(\'$2$4\', true, \'$1\')';
		}
		else
		{
			$replace[] = 'handle_img_tag(\'$1$3\', false)';
			$replace[] = 'handle_img_tag(\'$2$4\', false, \'$1\')';

			$pattern[] = '#\[imgr\]((ht|f)tps?://)([^\s<"]*?)\[/imgr\]#e';
			$pattern[] = '#\[imgr=([^\[]*?)\]((ht|f)tps?://)([^\s<"]*?)\[/imgr\]#e';
			$pattern[] = '#\[imgl\]((ht|f)tps?://)([^\s<"]*?)\[/imgl\]#e';
			$pattern[] = '#\[imgl=([^\[]*?)\]((ht|f)tps?://)([^\s<"]*?)\[/imgl\]#e';

			$replace[] = 'handle_img_tag(\'$1$3\', false, null,\'right\')';
			$replace[] = 'handle_img_tag(\'$2$4\', false, \'$1\', \'right\')';
			$replace[] = 'handle_img_tag(\'$1$3\', false, null,\'left\')';
			$replace[] = 'handle_img_tag(\'$2$4\', false, \'$1\', \'left\')';
		}
	}

	$pattern[] = '#\[url\]([^\[]*?)\[/url\]#e';
	$pattern[] = '#\[url=([^\[]+?)\](.*?)\[/url\]#e';
	$pattern[] = '#\[email\]([^\[]*?)\[/email\]#';
	$pattern[] = '#\[email=([^\[]+?)\](.*?)\[/email\]#';

	$replace[] = 'handle_url_tag(\'$1\')';
	$replace[] = 'handle_url_tag(\'$1\', \'$2\')';
	$replace[] = '<a href="mailto:$1">$1</a>';
	$replace[] = '<a href="mailto:$1">$2</a>';

	// This thing takes a while! :)
	$text = preg_replace($pattern, $replace, $text);

	return $text;
}


//
// Make hyperlinks clickable
//
function do_clickable($text)
{
	$text = ' '.$text;

	$text = preg_replace('#(?<=[\s\]\)])(<)?(\[)?(\()?([\'"]?)(https?|ftp|news){1}://([\w\-]+\.([\w\-]+\.)*\w+(:[0-9]+)?(/[^\s\[]*[^\s.,?!\[;:-])?)\4(?(3)(\)))(?(2)(\]))(?(1)(>))(?![^\s]*\[/(?:url|img|imgl|imgr|video|youtube|audio)\])#ie', 'stripslashes(\'$1$2$3$4\').handle_url_tag(\'$5://$6\', \'$5://$6\', true).stripslashes(\'$4$10$11$12\')', $text);
	$text = preg_replace('#(?<=[\s\]\)])(<)?(\[)?(\()?([\'"]?)(www|ftp)\.(([\w\-]+\.)*\w+(:[0-9]+)?(/[^\s\[]*[^\s.,?!\[;:-])?)\4(?(3)(\)))(?(2)(\]))(?(1)(>))(?![^\s]*\[/(?:url|img|imgl|imgr|video|youtube|audio)\])#ie', 'stripslashes(\'$1$2$3$4\').handle_url_tag(\'$5.$6\', \'$5.$6\', true).stripslashes(\'$4$10$11$12\')', $text);

	return substr($text, 1);
}


//
// Convert a series of smilies to images
//
function do_smilies($text)
{
	global $DBC_config, $smilies;

	$text = ' '.$text.' ';

	foreach ($smilies as $smiley_text => $smiley_img)
	{
		if (strpos($text, $smiley_text) !== false)
			$text = preg_replace("#(?<=[>\s])".preg_quote($smiley_text, '#')."(?=\W)#m", '<img src="'.$DBC_config['o_base_url'].'/engine/skins/emoticons/'.$smiley_img.'" alt="'.substr($smiley_img, 0, strrpos($smiley_img, '.')).'" />', $text);
	}

	return substr($text, 1, -1);
}


//
// Parse message text
//
function parse_message($text, $hide_smilies)
{
	global $DBC_config, $lang_common, $DBC_user,$sword;

	if($sword!=null)
	{
		$word_array=explode('-',$sword);
		while (list($i, $word) = @each($word_array))
			{
				if($word!='and' && $word!='or' && $word!='not')
					$text=str_ireplace($word,'[h]'.$word.'[/h]',$text);
			}
	}

	if ($DBC_config['o_censoring'] == '1')
		$text = censor_words($text);

	// Convert applicable characters to HTML entities
	$text = DBC_htmlspecialchars($text);

	// If the message contains a code tag we have to split it up (text within [code][/code] shouldn't be touched)
	if (strpos($text, '[code]') !== false && strpos($text, '[/code]') !== false)
	{
		list($inside, $outside) = split_text($text, '[code]', '[/code]', $errors);
		$text = implode("\1", $outside);
	}


	if ($DBC_config['p_message_bbcode'] == '1' && strpos($text, '[') !== false && strpos($text, ']') !== false)
		$text = do_bbcode($text);

	if ($DBC_config['o_smilies'] == '1' && $DBC_user['show_smilies'] == '1' && $hide_smilies == '0')
		$text = do_smilies($text);

	// Deal with newlines, tabs and multiple spaces
	$pattern = array("\n", "\t", '  ', '  ');
	$replace = array('<br />', '&#160; &#160; ', '&#160; ', ' &#160;');
	$text = str_replace($pattern, $replace, $text);


	// If we split up the message before we have to concatenate it together again (code tags)
	if (isset($inside))
	{
		$outside = explode("\1", $text);
		$text = '';

		$num_tokens = count($outside);

		for ($i = 0; $i < $num_tokens; ++$i)
		{
			$text .= $outside[$i];
			if (isset($inside[$i]))
			//	$text .= '</p><div class="codebox"><pre><code>'.DBC_trim($inside[$i], "\n\r").'</code></pre></div><p>';
			{
				$num_lines = (substr_count($inside[$i], "\n"));
				$text .= '</p><div class="codebox"><pre'.(($num_lines > 28) ? ' class="vscroll"' : '').'><code>'.DBC_trim($inside[$i], "\n\r").'</code></pre></div><p>';
			}
		}
	}

	// Add paragraph tag around post, but make sure there are no empty paragraphs
	$text = preg_replace('#<br />\s*?<br />((\s*<br />)*)#i', "</p>$1<p>", $text);
	$text = str_replace('<p><br />', '<p>', $text);
	$text = str_replace('<p></p>', '', '<p>'.$text.'</p>');


	return $text;

}


//
// Parse signature text
//
function parse_signature($text)
{
	global $DBC_config, $lang_common, $DBC_user;

	if ($DBC_config['o_censoring'] == '1')
		$text = censor_words($text);

	// Convert applicable characters to HTML entities
	$text = DBC_htmlspecialchars($text);

	if ($DBC_config['p_sig_bbcode'] == '1' && strpos($text, '[') !== false && strpos($text, ']') !== false)
		$text = do_bbcode($text, true);

	if ($DBC_config['o_smilies_sig'] == '1' && $DBC_user['show_smilies'] == '1')
		$text = do_smilies($text);


	// Deal with newlines, tabs and multiple spaces
	$pattern = array("\n", "\t", '  ', '  ');
	$replace = array('<br />', '&#160; &#160; ', '&#160; ', ' &#160;');
	$text = str_replace($pattern, $replace, $text);

	// Add paragraph tag around post, but make sure there are no empty paragraphs
	$text = preg_replace('#<br />\s*?<br />((\s*<br />)*)#i', "</p>$1<p>", $text);
	$text = str_replace('<p><br />', '<p>', $text);
	$text = str_replace('<p></p>', '', '<p>'.$text.'</p>');

	return $text;
}
